iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
Software Development

Java 17 新登場系列 第 3

Day 3 - java.util.function 套件

  • 分享至 

  • xImage
  •  

昨天介紹了 Lambda 表達式, 廣泛地說只要介面只有一個抽象方法就可以使用 Lambda 表達式,而 在 Java 標準程式庫裡面,有個套件專門用來存放會被程式庫其他部分重複使用的泛函介面,這個套件稱為java.util.function,套件有四個介面定義:

  • Consumer
  • Supplier
  • Predicate
  • Function

Consumer

java.util.function.Consumer 介面包含了兩個方法

void accept(T t)

以下是一個簡單的範例,把字串串列 println 出來

Part 1:內部匿名類別的實作
這裡是 java.util.Iterable 的 default 方法(List 繼承自 Iterable,也接收了 forEach 方法) forEach 接受了 Consumer 引數
Part 2:Lambda 表達式
Part 3:方法參考

//Part 1
List<String> strings = Arrays.asList("this", "is", "a", "list", "of", "strings");
strings.forEach(new Consumer<String>(){
	@Override
	public void accept(String s){
		System.out.println(s);
  }
});

//Part 2
strings.forEach(s -> System.out.println(s));

//Part 3
strings.forEach(System.out::println);

Supplier

java.util.function.Consumer 介面抽象方法如下,不接受任何引數產生一個物件:

T get()

以下是一個簡單的例子,使用 log 輸出一個隨機數
Part 1:內部匿名類別的實作
Part 2:Lambda 表達式
Part 3:方法參考

// Part 1
DoubleSupplier randomSupplier = new DoubleSupplier() {
    @Override
    public double getAsDouble() {
        return Math.random();
    }
};

//Part 2
randomSupplier = () -> Math.random();
randomSupplier = Math::random;

// deferred execution
Logger logger = Logger.getLogger(this.getClass().getName());
logger.debug(randomSupplier); 
logger.debug(Math.random()); // must execution

使用 Supplier 一個主要用途是支援延遲執行(deferred execution),的概念,如果 T get() 這個 T 物件的建立成本很高,不透過 supplier 產生物件可能就是 new 一個出來使用,再根據場景作要不要使用的處理,著名的例子是 logger 在上例裡面如果 log level 設定為 info 則 randomSupplier 裡面的Math.random(); 並不會執行,同樣如果我們使用 logger.debug(Math.random()); 則 Math.random() 一定會被執行

Predicate

java.util.function.Predicate 介面抽象方法如下,主要的目的是篩選串流:

boolean test(T t)

以下是一個簡單的例子,印出比 5 大的數字:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> collect = list.stream()
								.filter(x -> x > 5).collect(Collectors.toList());
System.out.println(collect);

Function

java.util.function.Function 介面抽象方法如下,主要的目的是將輸入參數轉成輸出值:

R apply(T t)

以下是一個簡單的例子,map 利用 Function 將 String 串列轉換成 Stream,最後再轉成List:
Part 1:內部匿名類別的實作
Part 2:Lambda 表達式
Part 3:方法參考

List<String> names = Arrays.asList("Mal", "Wash", "Kaylee", "Inara",
                "Zoë", "Jayne", "Simon", "River", "Shepherd Book");

//Part 1
List<Integer> nameLengths = 
								names.stream().map(new Function<String, Integer>() {
                    @Override
                    public Integer apply(String s) {
                        return s.length();
                    }
                })
                .collect(Collectors.toList());

//Part 2
nameLengths = names.stream()
        .map(s -> s.length())
        .collect(Collectors.toList());

// Part 3
nameLengths = names.stream()
        .map(String::length)
        .collect(Collectors.toList());

參考資料:

現代Java:輕鬆解決Java 8 與 9 的難題 - 歐萊禮 2018
https://www.geeksforgeeks.org/java-8-predicate-with-examples/?ref=lbp


上一篇
Day 2 - Lambda 表達式
下一篇
Day 4 - 串流操作 1
系列文
Java 17 新登場8
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言